/**

  ******************************************************************************

  * @file    stm324x9i_eval_sd.c

  * @author  MCD Application Team

  * @brief   This file includes the uSD card driver mounted on STM324x9I-EVAL

  *          evaluation board.

  ******************************************************************************

  * @attention

  *

  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>

  *

  * Redistribution and use in source and binary forms, with or without modification,

  * are permitted provided that the following conditions are met:

  *   1. Redistributions of source code must retain the above copyright notice,

  *      this list of conditions and the following disclaimer.

  *   2. Redistributions in binary form must reproduce the above copyright notice,

  *      this list of conditions and the following disclaimer in the documentation

  *      and/or other materials provided with the distribution.

  *   3. Neither the name of STMicroelectronics nor the names of its contributors

  *      may be used to endorse or promote products derived from this software

  *      without specific prior written permission.

  *

  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR

  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER

  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  *

  ******************************************************************************

  */ 



/* File Info : -----------------------------------------------------------------

                                   User NOTES

1. How To use this driver:

--------------------------

   - This driver is used to drive the micro SD external card mounted on STM324x9I-EVAL 

     evaluation board.

   - This driver does not need a specific component driver for the micro SD device

     to be included with.



2. Driver description:

---------------------

  + Initialization steps:

     o Initialize the micro SD card using the BSP_SD_Init() function. This 

       function includes the MSP layer hardware resources initialization and the

       SDIO interface configuration to interface with the external micro SD. It 

       also includes the micro SD initialization sequence.

     o To check the SD card presence you can use the function BSP_SD_IsDetected() which 

       returns the detection status 

     o If SD presence detection interrupt mode is desired, you must configure the 

       SD detection interrupt mode by calling the function BSP_SD_ITConfig(). The interrupt 

       is generated as an external interrupt whenever the micro SD card is 

       plugged/unplugged in/from the evaluation board. The SD detection interrupt

       is handled by calling the function BSP_SD_DetectIT() which is called in the IRQ

       handler file, the user callback is implemented in the function BSP_SD_DetectCallback().

     o The function BSP_SD_GetCardInfo() is used to get the micro SD card information 

       which is stored in the structure "HAL_SD_CardInfoTypeDef".

  

     + Micro SD card operations

        o The micro SD card can be accessed with read/write block(s) operations once 

          it is ready for access. The access can be performed whether using the polling

          mode by calling the functions BSP_SD_ReadBlocks()/BSP_SD_WriteBlocks(), or by DMA 

          transfer using the functions BSP_SD_ReadBlocks_DMA()/BSP_SD_WriteBlocks_DMA()

        o The DMA transfer complete is used with interrupt mode. Once the SD transfer

          is complete, the SD interrupt is handled using the function BSP_SD_IRQHandler(),

          the DMA Tx/Rx transfer complete are handled using the functions

          BSP_SD_DMA_Tx_IRQHandler()/BSP_SD_DMA_Rx_IRQHandler(). The corresponding user callbacks 

          are implemented by the user at application level. 

        o The SD erase block(s) is performed using the function BSP_SD_Erase() with specifying

          the number of blocks to erase.

        o The SD runtime status is returned when calling the function BSP_SD_GetCardState().



 

------------------------------------------------------------------------------*/ 



/* Includes ------------------------------------------------------------------*/

#include "sdio_sd.h"



/** @addtogroup BSP

  * @{

  */



/** @addtogroup STM324x9I_EVAL

  * @{

  */ 

  

/** @defgroup STM324x9I_EVAL_SD STM324x9I EVAL SD

  * @{

  */ 



/** @defgroup STM324x9I_EVAL_SD_Private_Variables SD Private Variables

  * @{

  */

SD_HandleTypeDef uSdHandle;



/**

  * @}

  */ 



/** @defgroup STM324x9I_EVAL_SD_Private_Functions SD Private Functions

  * @{

  */



/**

  * @brief  Initializes the SD card device.

  * @retval SD status

  */

uint8_t BSP_SD_Init(void)

{ 

  uint8_t SD_state = MSD_OK;

  

  /* uSD device interface configuration */

  uSdHandle.Instance = SDIO;



  uSdHandle.Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;

  uSdHandle.Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;

  uSdHandle.Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;

  uSdHandle.Init.BusWide             = SDIO_BUS_WIDE_1B;

  uSdHandle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;

  uSdHandle.Init.ClockDiv            = SDIO_TRANSFER_CLK_DIV;



  /* Msp SD initialization */

  BSP_SD_MspInit(&uSdHandle, NULL);

  

  if(HAL_SD_Init(&uSdHandle) != HAL_OK)

  {

    SD_state = MSD_ERROR;

  }

  

  /* Configure SD Bus width */

  if(SD_state == MSD_OK)

  {

    /* Enable wide operation */

    if(HAL_SD_ConfigWideBusOperation(&uSdHandle, SDIO_BUS_WIDE_4B) != HAL_OK)

    {

      SD_state = MSD_ERROR;

    }

    else

    {

      SD_state = MSD_OK;

    }

  }

  

  return  SD_state;

}



/**

  * @brief  Configures Interrupt mode for SD detection pin.

  * @retval Returns 0

  */

uint8_t BSP_SD_ITConfig(void)

{  

  /* Configure Interrupt mode for SD detection pin */  

//  BSP_IO_ConfigPin(SD_DETECT_PIN, IO_MODE_IT_FALLING_EDGE);

  

  return 0;

}



/**

 * @brief  Detects if SD card is correctly plugged in the memory slot or not.

 * @retval Returns if SD is detected or not

 */

uint8_t BSP_SD_IsDetected(void)

{

  __IO uint8_t status = SD_PRESENT;

  

//  /* Check SD card detect pin */

//  if(BSP_IO_ReadPin(SD_DETECT_PIN))

//  {

//    status = SD_NOT_PRESENT;

//  }

  

  return status;

}



/** @brief  SD detect IT treatment.

  * @retval None

  */

void BSP_SD_DetectIT(void)

{

//  /* Clear all pending bits */

//  BSP_IO_ITClear();

//  

//  /* To re-enable IT */

//  BSP_SD_ITConfig();

//  

//  /* SD detect IT callback */

//  BSP_SD_DetectCallback();

}



/** @brief  SD detect IT detection callback

  * @retval None

  */

__weak void BSP_SD_DetectCallback(void)

{

  /* NOTE: This function Should not be modified, when the callback is needed,

     the BSP_SD_DetectCallback could be implemented in the user file

  */ 

}



/**

  * @brief  Reads block(s) from a specified address in an SD card, in polling mode.

  * @param  pData: Pointer to the buffer that will contain the data to transmit

  * @param  ReadAddr: Address from where data is to be read

  * @param  NumOfBlocks: Number of SD blocks to read

  * @param  Timeout: Timeout for read operation

  * @retval SD status

  */

uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)

{

  if(HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)

  {

    return MSD_ERROR;

  }

  else

  {

    return MSD_OK;

  }

}



/**

  * @brief  Writes block(s) to a specified address in an SD card, in polling mode. 

  * @param  pData: Pointer to the buffer that will contain the data to transmit

  * @param  WriteAddr: Address from where data is to be written

  * @param  NumOfBlocks: Number of SD blocks to write

  * @param  Timeout: Timeout for write operation

  * @retval SD status

  */

uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)

{

  if(HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)

  {

    return MSD_ERROR;

  }

  else

  {

    return MSD_OK;

  }

}



/**

  * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.

  * @param  pData: Pointer to the buffer that will contain the data to transmit

  * @param  ReadAddr: Address from where data is to be read

  * @param  NumOfBlocks: Number of SD blocks to read 

  * @retval SD status

  */

uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)

{  

  /* Read block(s) in DMA transfer mode */

  if(HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)

  {

    return MSD_ERROR;

  }

  else

  {

    return MSD_OK;

  }

}



/**

  * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.

  * @param  pData: Pointer to the buffer that will contain the data to transmit

  * @param  WriteAddr: Address from where data is to be written

  * @param  NumOfBlocks: Number of SD blocks to write 

  * @retval SD status

  */

uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)

{ 

  /* Write block(s) in DMA transfer mode */

  if(HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)

  {

    return MSD_ERROR;

  }

  else

  {

    return MSD_OK;

  }

}



/**

  * @brief  Erases the specified memory area of the given SD card. 

  * @param  StartAddr: Start byte address

  * @param  EndAddr: End byte address

  * @retval SD status

  */

uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)

{

  if(HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) != HAL_OK)

  {

    return MSD_ERROR;

  }

  else

  {

    return MSD_OK;

  }

}



/**

  * @brief  Initializes the SD MSP.

  * @param  hsd: SD handle

  * @param  Params : pointer on additional configuration parameters, can be NULL.

  */

__weak void BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params)

{

  static DMA_HandleTypeDef dmaRxHandle;

  static DMA_HandleTypeDef dmaTxHandle;

  GPIO_InitTypeDef GPIO_Init_Structure;

  

  /* Enable SDIO clock */

  __HAL_RCC_SDIO_CLK_ENABLE();

  

  /* Enable DMA2 clocks */

  __DMAx_TxRx_CLK_ENABLE();



  /* Enable GPIOs clock */

  __HAL_RCC_GPIOC_CLK_ENABLE();

  __HAL_RCC_GPIOD_CLK_ENABLE();

  

  /* Common GPIO configuration */

  GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;

  GPIO_Init_Structure.Pull      = GPIO_PULLUP;

  GPIO_Init_Structure.Speed     = GPIO_SPEED_HIGH;

  GPIO_Init_Structure.Alternate = GPIO_AF12_SDIO;

  

  /* GPIOC configuration */

  GPIO_Init_Structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;

   

  HAL_GPIO_Init(GPIOC, &GPIO_Init_Structure);



  /* GPIOD configuration */

  GPIO_Init_Structure.Pin = GPIO_PIN_2;

  HAL_GPIO_Init(GPIOD, &GPIO_Init_Structure);



  /* NVIC configuration for SDIO interrupts */

  HAL_NVIC_SetPriority(SDIO_IRQn, 0x0E, 0);

  HAL_NVIC_EnableIRQ(SDIO_IRQn);

    

  /* Configure DMA Rx parameters */

  dmaRxHandle.Init.Channel             = SD_DMAx_Rx_CHANNEL;

  dmaRxHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;

  dmaRxHandle.Init.PeriphInc           = DMA_PINC_DISABLE;

  dmaRxHandle.Init.MemInc              = DMA_MINC_ENABLE;

  dmaRxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

  dmaRxHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;

  dmaRxHandle.Init.Mode                = DMA_PFCTRL;

  dmaRxHandle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;

  dmaRxHandle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;

  dmaRxHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;

  dmaRxHandle.Init.MemBurst            = DMA_MBURST_INC4;

  dmaRxHandle.Init.PeriphBurst         = DMA_PBURST_INC4;

  

  dmaRxHandle.Instance = SD_DMAx_Rx_STREAM;

  

  /* Associate the DMA handle */

  __HAL_LINKDMA(hsd, hdmarx, dmaRxHandle);

  

  /* Deinitialize the stream for new transfer */

  HAL_DMA_DeInit(&dmaRxHandle);

  

  /* Configure the DMA stream */

  HAL_DMA_Init(&dmaRxHandle);

  

  /* Configure DMA Tx parameters */

  dmaTxHandle.Init.Channel             = SD_DMAx_Tx_CHANNEL;

  dmaTxHandle.Init.Direction           = DMA_MEMORY_TO_PERIPH;

  dmaTxHandle.Init.PeriphInc           = DMA_PINC_DISABLE;

  dmaTxHandle.Init.MemInc              = DMA_MINC_ENABLE;

  dmaTxHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

  dmaTxHandle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;

  dmaTxHandle.Init.Mode                = DMA_PFCTRL;

  dmaTxHandle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;

  dmaTxHandle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;

  dmaTxHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;

  dmaTxHandle.Init.MemBurst            = DMA_MBURST_INC4;

  dmaTxHandle.Init.PeriphBurst         = DMA_PBURST_INC4;

  

  dmaTxHandle.Instance = SD_DMAx_Tx_STREAM;

  

  /* Associate the DMA handle */

  __HAL_LINKDMA(hsd, hdmatx, dmaTxHandle);

  

  /* Deinitialize the stream for new transfer */

  HAL_DMA_DeInit(&dmaTxHandle);

  

  /* Configure the DMA stream */

  HAL_DMA_Init(&dmaTxHandle); 

  

  /* NVIC configuration for DMA transfer complete interrupt */

  HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, 0x0F, 0);

  HAL_NVIC_EnableIRQ(SD_DMAx_Rx_IRQn);

  

  /* NVIC configuration for DMA transfer complete interrupt */

  HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, 0x0F, 0);

  HAL_NVIC_EnableIRQ(SD_DMAx_Tx_IRQn);

}



/**

  * @brief  Gets the current SD card data status.

  * @retval Data transfer state.

  *          This value can be one of the following values:

  *            @arg  SD_TRANSFER_OK: No data transfer is acting

  *            @arg  SD_TRANSFER_BUSY: Data transfer is acting

  */

uint8_t BSP_SD_GetCardState(void)

{

  return((HAL_SD_GetCardState(&uSdHandle) == HAL_SD_CARD_TRANSFER ) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);

}

  



/**

  * @brief  Get SD information about specific SD card.

  * @param  CardInfo: Pointer to HAL_SD_CardInfoTypedef structure

  * @retval None 

  */

void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo)

{

  /* Get SD card Information */

  HAL_SD_GetCardInfo(&uSdHandle, CardInfo);

}



/**

  * @brief SD Abort callbacks

  * @param hsd: SD handle

  * @retval None

  */

void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)

{

  BSP_SD_AbortCallback();

}



/**

  * @brief Tx Transfer completed callbacks

  * @param hsd: SD handle

  * @retval None

  */

void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)

{

  BSP_SD_WriteCpltCallback();

}



/**

  * @brief Rx Transfer completed callbacks

  * @param hsd: SD handle

  * @retval None

  */

void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)

{

  BSP_SD_ReadCpltCallback();

}



/**

  * @brief BSP SD Abort callbacks

  * @retval None

  */

__weak void BSP_SD_AbortCallback(void)

{



}



/**

  * @brief BSP Tx Transfer completed callbacks

  * @retval None

  */

__weak void BSP_SD_WriteCpltCallback(void)

{



}



/**

  * @brief BSP Rx Transfer completed callbacks

  * @retval None

  */

__weak void BSP_SD_ReadCpltCallback(void)

{



}



/**

  * @}

  */ 



/**

  * @}

  */ 



/**

  * @}

  */ 



/**

  * @}

  */

 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
